Method and apparatus for requesting and performing batched operations for web services

ABSTRACT

The Web Services Development Kit (WSDK) comprises a set of build-time tools and run-time components designed to support the development of web services and the interface to those services. WSDK provides a framework for the development of web services that isolates developers from the implementation details of the markup and transport layers, by separating the logical aspects of the service development from the physical aspects. A “call” generated by a client contains a batch of operations to be executed in the context of a single request/reply message exchange. A markup library translates logical structure to a specific markup language. Additional markup languages are supported by adding additional modules to the markup library.

[0001] This application claims the benefit of U.S. Provisional patentapplication No. 60/364,480 filed on Mar. 14, 2002 and U.S. Provisionalpatent application No. 60/364,862 filed on Mar. 14, 2002, each of whichis incorporated herein by reference.

FIELD OF THE INVENTION

[0002] At least one embodiment of the present invention pertains totools and components for the development of web services and, moreparticularly, to a method and apparatus for requesting and performingbatched operations for Web Services.

BACKGROUND

[0003] “Web services” is an industry term that covers a collection ofstandards and proposals that define how distributed computing should beimplemented in a web-based network environment, such as the World WideWeb. Web services is an evolving area of technology that has a broadrange of potential applications but is immature in implementation. Thereare several general attributes that describe the essence of webservices.

[0004] The primary paradigm for web services is that of a client/serverrelationship. A client sends a request to a server for the execution ofsome task. The server executes the task and sends an appropriate replyback to the client.

[0005] Interoperability is a main goal of current web services efforts.Applying lessons from past mistakes, the industry is focusing itsefforts on ensuring that information communicated between components ofthe system will be interpreted identically by all of the partiesinvolved. The focus on “on the wire” representation has allowed for thedevelopment of very different (and competing) technologies forconstructing web service implementations. Two of the major contenders atpresent include Microsoft, with its NET architecture that leverages itstraditional COM technology, and IBM, with its WebSphere architecturethat leverages such Java technologies as Java 2 Enterprise Edition(J2EE).

[0006] Communication between client and server on the World Wide Web istypically accomplished via Hypertext Transport Protocol (HTTP). This isone of the factors that distinguish web services from otherclient/server approaches, such as remote procedure call (RPC) or commonobject request broker architecture (CORBA). Web service interactionsalso differ from those of typical Web browser interactions. In thetypical browser interaction, the client sends a request for content fromthe server which will be rendered for display to an end user. In the webservices model, the client sends a request for a task (or operation) tobe executed by the server, and the reply contains the results ofexecuting that operation.

[0007] Underlying most aspects of web services is the extensible markuplanguage (XML). Most situations that call for representation of dataemploy XML as the base data structuring language. Most web servicesprotocols are defined as a set of XML elements and conventions. This isanother major factor that distinguishes web services from otherclient/server approaches. For example, CORBA employs one language (IDL)for defining interfaces and a different protocol (IIOP) forcommunicating between client and server. In the web services context,both the interface definition language and the client/servercommunication protocol are represented in XML.

[0008] There are two problems with XML, however, that probably originatefrom its original focus on supporting text processing. First, XML can bequite difficult and expensive to parse, due to such features asuser-defined entities, processing instructions, etc., most of which arenot needed for most inter-application communication. Second, as atext-based protocol, XML does not support the transport of raw binaryinformation. Instead, it must be encoded into text for transmission(e.g., Base64 or similar encoding mechanisms).

[0009] There are essentially two approaches typically used for solvingthe first problem. The first approach is to define protocols that arebased on the important core features of XML, but specifically forbid theuse of particularly complex XML features (such as processinginstructions). A recent example of this approach is the Simple ObjectAccess Protocol (SOAP). See “Simple Object Access Protocol (SOAP) 1.1,”W3C Note, May 8, 2000. SOAP is an XML-based protocol that provides basicrules for the format of request and reply messages exchanged betweenclient and server during operation execution. The second approach is todefine a separate “logical” document model and then provide informationto “map” that logical model onto the specific XML representation. Arecent example of this approach is the Web Services Description Language(WSDL). See “Web Services Description Language (WSDL) 1.1,” W3C Note,Mar. 15, 2001. WSDL is an XML-based interface definition language thatis used to define the operations supported by a server and how requestsand replies for those operations are represented in the messagesexchanged between client and server.

[0010] SOAP defines four basic things:

[0011] 1) A subset of XML grammar that is allowed in a SOAP message(basically, it disallows certain complex XML constructs that aredifficult to parse and are not applicable to a remote method invocationparadigm);

[0012] 2) A basic document structure for SOAP messages that include:

[0013] a top level SOAP “Envelope” element within which all SOAP-relatedXML data must reside,

[0014] a SOAP “Header” element which is intended to contain allinformation pertaining to routing and handling of the SOAP document, and

[0015] a SOAP “Body” element which is intended to contain allinformation pertaining to execution of the specific request (or reply);

[0016] 3) How “faults” (document processing or task execution errors)should be represented within the document; and

[0017] 4) A suggested approach for representing typed data in SOAPdocuments (e.g., mappings from low-level host programming languagevariable types to XML).

[0018] WSDL defines a grammar for describing web service interfaces. AWSDL interface description consists of the following five top-levelelements:

[0019] 1) A single types element. Within this element, you define thelogical types that you will be referencing later in the specification.Types may be simple (refer to single elements) or complex (combinationsof elements, e.g. struct or array). Different typing systems may be usedhere, but the most common one employed is XML Schema;

[0020] 2) A set of message elements. A message element corresponds to asingle logical “message” that will be sent from client to server or viceversa. Messages consist of “parts”—each part has a type (defined withinthe types element);

[0021] 3) A set of portType elements. A portType element corresponds tosingle logical service definition. Port types consist of a set ofoperation definitions. An operation has a name and the set of messagesinvolved in requesting execution of that operation (typically a requestmessage, a reply message, and a fault message);

[0022] 4) A set of binding elements. Up to this point, everythingcovered in the WSDL document represents a “logical” view of the service.The purpose of the binding elements is to define how the logicalmessages are represented in a particular markup language/transport.Support theoretically exists for several XML-based transports, but themost common binding is to SOAP/HTTP. In that case, the binding involvesmapping each part of each message to the appropriate section of the SOAPdocument and identifying the approach that will be used for encoding thelogically-defined data types in SOAP (typically the SOAP encoding rulesare used here); and

[0023] 5) A service element. Where the binding element is used to mapthe logical representation to a markup/transport, the service element isused to identify the physical locations that support a particularportType/binding pair. For the typical SOAP-HTTP binding, this wouldnormally consist of uniform resource locators (URLs) (including host andport).

[0024] A full WSDL specification thus consists of logical information(types, messages and portTypes), physical information (bindings), andlocation information (services). Since this information is typicallyneeded by clients at different points in the development, WSDLspecifications are often produced in fragments that are assembledtogether via an analog of the C pre-processor “#include” directive.

[0025] Aside from SOAP and WSDL, there are other initiatives that areoften considered web services “building blocks”, such as XML schema anduniversal description, discovery, and integration (UDDI) protocol. XMLschema provides a set of rules for defining logical data types in XMLand is the preferred language for defining types in WSDL. UDDI is anXML-based protocol for obtaining information about the services providedby a particular organization. Typically, UDDI is used to retrieve thecomplete WSDL specifications (including location information) for a setof operations.

[0026] Combined, SOAP and WSDL perform three basic tasks when mappinginformation exchange onto a structured document:

[0027] 1) Define a logical model for the interchange (the “parse tree”view of the problem). WSDL provides this.

[0028] 2) Define a physical model for the interchange (the “on the wire”representation). SOAP provides this.

[0029] 3) Provide a mapping between the logical and physical models.WSDL provides this.

[0030] Consider the following sequence of events, which describes atypical experience for a web services client developer:

[0031] The developer first obtains the “logical” portion of WSDLspecifications for operations of interest via an “out of band” method,such as email or downloading from a web site.

[0032] The Developer imports the WSDL specifications into a web servicestoolkit and generates a native language (e.g., Java) client applicationprogramming interface (API) and writes code to that API.

[0033] At runtime, a complete WSDL specification for the operations ofinterest is obtained via UDDI from a service “registry” at the deployedsite. The additional binding and location information in the “complete”WSDL files is necessary for actual communication between client andserver (though it does not change the client API originally generated).

[0034] When runtime calls are made via the generated client API, theyare translated into SOAP documents that are sent to the server via anHTTP POST. The server executes the requested operation and returns theresults as a SOAP document via the HTTP POST reply. The returneddocument is parsed and used to populate the appropriate “output”parameters in the client API.

[0035] The two basic approaches represented by SOAP and WSDL haveshortcomings. For example, SOAP does not define how one represents thetasks to be executed by the server, how the data associated with therequest and reply is structured, relationships between request and replymessages, or real-world issues such as application versioning. Theseissues must be coordinated between client and server “out of band”. WSDLaddresses the “logical to physical” mapping problem by individuallyspecifying how different elements in the logical model map to theircounterparts in the physical model. Consequently, a consumer of such aninterface must parse and understand such mapping instructions, which isnot a trivial task. In addition, SOAP and WSDL are both XML-based.Consequently, without either changing the XML specification ormanipulating the underlying transport (e.g., HTTP) protocol, one cannotpass binary data without encoding it as text. Other problems areassociated with SOAP and WSDL, as described below.

[0036] Further, additional facilities are needed for effectiveimplementation of typical web services, which are not provided by knowncurrent specifications. These facilities include user identification andauthentication, access control, version management, transactionmanagement, and ad hoc (dynamic) “batching” (sending several logicaloperation requests together in a single physical message).

SUMMARY OF THE INVENTION

[0037] The present invention includes a method and a correspondingapparatus, where the method includes dynamically determining in a clienta plurality of batched operations to be performed by a server for theclient during execution of a web based network application. This isaccomplished by selecting a portion of an operation structure previouslydefined using a structured language. The method further includesoperating the client to specify the plurality of batched operations in arequest, and sending the request from the client to the server torequest the server to perform the plurality of operations in a batchedmode.

[0038] Other features of the present invention will be apparent from theaccompanying drawings and from the detailed description which follows.

BRIEF DESCRIPTION OF THE DRAWINGS

[0039] One or more embodiments of the present invention are illustratedby way of example and not limitation in the figures of the accompanyingdrawings, in which like references indicate similar elements and inwhich:

[0040]FIG. 1 illustrates a high-level view of the WSDK architecture;

[0041]FIG. 2 shows a process performed by a service developer during aWSDK-based development project;

[0042]FIG. 3 shows an example of a network environment in which WSDK canbe implemented;

[0043]FIG. 4A shows components of the WSDK Server Framework;

[0044]FIG. 4B shows components of the WSDK Client API Framework;

[0045]FIG. 5 is a high-level block diagram of the WSDK Library;

[0046]FIG. 6 shows components of the input module of the WSDK Library;

[0047]FIG. 7 shows an overall process for a document exchange between aclient and a server using the WSDK APIs;

[0048]FIG. 8 shows a process performed by the client during the documentexchange;

[0049]FIG. 9 shows a process performed by the server during the documentexchange; and

[0050]FIG. 10 is a block diagram showing an abstraction of a processingsystem that can be used to implement the WSDK and related techniques.

DETAILED DESCRIPTION

[0051] A method and apparatus for requesting and performing batchedoperations for Web Services are described. Note that in thisdescription, references to “one embodiment” or “an embodiment” mean thatthe feature being referred to is included in at least one embodiment ofthe present invention. Further, separate references to “one embodiment”or “an embodiment” in this description do not necessarily refer to thesame embodiment; however, such embodiments are also not mutuallyexclusive unless so stated, and except as will be readily apparent tothose skilled in the art from the description. For example, a feature,structure, act, etc. described in one embodiment may also be included inother embodiments. Thus, the present invention can include a variety ofcombinations and/or integrations of the embodiments described herein.

I. Overview

[0052] As described in greater detail below, the present inventionintroduces a set of build-time tools and run-time components designed tosupport the development of web services and the interface to thoseservices. These tools and components are referred to collectively as WebServices Development Kit (WSDK). WSDK provides a framework for thedevelopment of web services that isolates developers from theimplementation details of the markup and transport layers. Inparticular, WSDK separates the logical aspects of the servicedevelopment from the physical aspects (markup and transport) so thatservice developers can focus on business logic and platform developerscan take care of mapping the logical model into particular markuplanguages (or versions of particular languages). Note that for purposesof this document, for ease of reference, different versions orvariations of a given markup language shall be treated as differentmarkup languages. WSDK provides additional support for real-worldapplication development and deployment issues not addressed in thestandard web services arena, such as batching, transaction management,and versioning, etc.

[0053] WSDK provides the above features in a form suitable for theextreme performance and scalability requirements of a carrier-classenvironment. For example, in certain embodiments of the invention: allserver-side code is written in low-overhead C and C++; there is minimaluse of dynamic memory allocation and string/data copying; hand-rolled“no copy” parsers are used with little or no dynamic memory allocation;and efficient code generated at build-time is used rather than run-timedata dictionary queries.

[0054] There are three main areas where WSDK differs conceptually fromthe service model defined by WSDL. First, the concept of “service”differs between WSDL and WSDK. In WSDL, a service may be viewed as a setof network end-points (host, port, and URI) that support a specificcollection of “bound” operations. WSDK, on the other hand, distinguishesbetween “server” (a run-time software unit that handles requests on anend-point) and “service” (a well-defined collection of operations moreakin to the WSDL “portType”). A WSDK server may host multiple services.In the remainder of this document, “service” will be used to mean atop-level aggregation of operations and related data types and faultcodes.

[0055] Second, WSDL defines a direct relationship between operations andmessages. Essentially, the entire content of a message is defined by thelogical content and binding method of a single operation. WSDK, on theother hand, introduces an intermediate runtime-only entity known as acall. A call contains a batch (one or more) of operations to be executedin the context of a single request/reply message exchange. Batching isan optional runtime decision made by the client and is only availablevia the client APIs provided with WSDK. A batch of operations is defineddynamically by a client, based on a previously defined (static)operation structure definition. Thus, a client may dynamically selectparticular portions of an operation structure definition to incorporateinto a message (a batched request), according to its current needsand/or the current state of application execution. Note that messagesgenerated from a call containing only one operation are identical tothose defined via WSDL.

[0056] Further, in WSDL the relationship between the logical operationrequest/reply structure and a particular markup language representationis specified via a declarative per-operation syntax. WSDK, on the otherhand, uses an entirely different mechanism, employing a markup librarythat can dynamically translates logical structure to any supportedmarkup language, without using any explicitly-declared binding oflogical structure to markup language encoding. Additional markuplanguages are supported by adding additional modules to the markuplibrary. Where explicit (e.g., WSDL) bindings are required, thehard-coded internal rules are simply translated into WSDL bindingstatements.

II. WSDK Architecture

[0057] To facilitate description of the present invention, variouscomponents are described herein as being implemented in a particularprogramming language, such as C, C++, or Java. It will be recognizedthat such references to particular programming languages refer only tocertain embodiments of the invention, and that in other embodiments, thedescribed components may be implemented in other programming languagesand/or by using hardware-based techniques.

[0058]FIG. 1 depicts a high-level view of the WSDK architectureaccording to one embodiment of the invention. There are four types ofcomponents depicted in FIG. 1: components of WSDK (indicated by thicksolid lines); components related to WSDK but not part of it (indicatedby thin solid lines); Operation Structure Definition (OSD)specifications; and generated code (depicted in dashed boxes).

[0059] The components of WSDK include a WSDK Code Generator1, a WSDKClient API Framework (WCAF) 2, a WSDK Server Framework (WSF) 3, and aWSDK Markup Library 4. The Code Generator 1, henceforth referred to as“OSDGen”, is a build-time generation tool that parses OperationStructure Definition (OSD) files and generates code for both serviceimplementation and client interface.

[0060] The WSF 3 is, in one embodiment, a C++ server framework thatmanages the runtime operation dispatch process and all associatedfacilities.

[0061] The WCAF 2 is, in certain embodiments, a C or Java clientframework that provides a framework within which client APIs areexposed. As described further below, this framework includes an“OipcCall” data structure that is populated with “OipcOperation”objects. The WCAF 2 also includes a set of functions to serialize therequest portion of the call to a request document and to populate thereply portion of the call from a reply document. In general, these“call-level” functions are simply wrappers over the operation-specificcode generated by OSDGen 1.

[0062] The Markup Library 4 is, in certain embodiments, a C or Javamarkup library that translates logical markup API calls into physicalmarkup (e.g., SOAP). This library 4 is used by both the WSF 3 and theWCAF 2.

[0063] The illustrated components related to WSDK include: a ServerTransport Framework 5; Operations, Administration, and Management (OA&M)facilities 6; and a Client Transport Library 7. Multiple implementationsof these components may exist.

[0064] The server transport framework (STF) 5 is responsible for thebasic runtime environment the server side. It may be, for example, aUNIX program that is designed to service “request” messages sent from aclient over a TCP socket. The STF 5 would typically be capable ofservicing multiple requests simultaneously (so it typically either hasmultiple threads or multiple processes) and may use HTTP as a“tunneling” protocol (e.g., requests are sent via an HTTP POST). The STF5 would typically allow for the separate development and integration ofmodules that implement service business logic.

[0065] The WSF 3 is provided in the form of a library that is linkedinto a main program, i.e., the STF 5. The STF 5 “drives” the WSF 3 viatwo interfaces: a “startup initialization” interface, and a “requestdispatch” interface. An example of the STF 5 for WSDK-based servers isthe Apache web server. This is combined with a small Apache module thatprovides the “glue” between Apache and WSF 3.

[0066] Thus, the “server-side” can be viewed as having three levels ofabstraction:

[0067] 1) The “server” level (provided by the STF)—a “main” program.

[0068] 2) The “service framework” level (provided by the WSF 3)—a“module” in the form of a library that is “plugged in” to the servermain program.

[0069] 3) The “service” level—a set of shared libraries (one for eachservice) that is “plugged in” to the WSF 3.

[0070] The OA&M facilities 6 are a set of configuration and loggingfacilities used by the WSF 3 via an abstract interface. Typically, theSTF 5 is responsible for initializing appropriate instances of thesefacilities.

[0071] The Client Transport Library 7 is used by the client forcommunication with WSDK-based servers when the generated WCAF 2 isemployed. The Client Transport Library 7 provides basic TCP/IPconnection management and client-side HTTP support.

[0072] Operation Structure Definition (OSD) Specifications 8 are inputfiles that are provided by developers and are described further below.

[0073] The generated code shown as dashed-line boxes 9 in FIG. 1includes components generated by OSDGen 1 and described in greaterdetail below.

[0074] The Service Implementations are the server-side code (e.g., C++)generated by OSDGen 1. They include a combination of type declarations,service initialization, operation serialization and validation, andskeletons for operation business logic.

[0075] The Service Client APIs 9A are the client-side code (e.g., C orJava) that corresponds to individual operations. This code includes acombination of type declarations and operation serialization logic.

[0076] The Service WSDL Specifications 9B are the WSDL specifications(logical and binding descriptions only) that correspond to theoperations of the service. They are provided as an alternative to usingthe client APIs. Note that WSDL location information (e.g., host andport) is not provided by WSDK, since it depends upon information knownonly at deployment. Clients that intend to use WSDL specifications mustobtain the location information via another facility.

[0077] Referring now to FIG. 2, a WSDK-based development project willnormally include the following process performed by the servicedeveloper:

[0078] Compose the OSD specification for the service (block 201), i.e.,construct the OSD file(s) for the service being defined, including thespecifications for each of the operations the service will provide. OSDand OSDGen 1 are described further below.

[0079] Run OSDGen 1 (block 202) to create the server-side operationcontext classes and the skeletons for the server-side service andoperation classes.

[0080] Complete the implementation of the generated server skeletonclasses and build the service into a shared library (block 203). Whenthis library is placed in a designated directory, the service willautomatically be loaded and initialized during WSF startupinitialization. This stage includes developing the set of utilityclasses that will be needed by the operation during execution.Typically, this might include code for interfacing with databasesystems, authenticating users, etc. Where appropriate, implement the“Transaction Member” interface for participation in the message-definedtransaction model.

[0081] Run OSDGen 1 again (with different options) to generate theclient-side interface artifacts (block 204), including: Logical andbinding portions of WSDL specifications for the service. Fault messagecatalogs that can then be localized for display of human-readable faultmessages; and client APIs.

[0082] Implement the execute( ) methods for each of the operationclasses (block 205).

II. Network Environment

[0083]FIG. 3 shows an example of a network environment in which WSDK andother aspects of the present invention may be implemented. Note,however, that the invention can also be implemented within many othernetwork configurations. As shown, a wireless client device 31 isconnected to a mobile access gateway (MAG) 32 through a wireless network33. The wireless client 31 device may be, for example, a cellulartelephone, personal digital assistant (PDA), two-way pager, or othersimilar device. The MAG 32 is connected to a number of servers 34through a wireline computer network (“wireline network”) 35, which maybe the Internet, for example. A second client device 36 is connected tothe server directly through the wireline network. Client device 36 maybe, for example, a conventional personal computer (PC), workstation, orother similar device.

[0084] The MAG 32 controls the connection to the wireless client device31 (session management), retrieving content from the origin server 4 onbehalf of the wireless client device 31 (proxying), and ensuring thatthe content is in a form that the wireless client device 31 canunderstand (translation). The MAG 32 may also perform many otherfunctions, such as billing, enhanced services, and push contentdelivery.

[0085] In various other embodiments, the wireline network 35 could be atype of network other than the Internet, such as a local area network(LAN), a private wide area network (WAN), or a corporate intranet.

[0086] One or more wireless client devices 31 can be connected to one ormore servers 34 on the wireline network 35 through the MAG 32. Likewise,one or more other client devices 36 can be connected to one or moreservers 34 in this manner directly through the wireline network 35. Anyof the clients and servers shown in FIG. 2 may implement WSDK and otherfeatures of the invention described herein.

[0087] As noted, the invention can also be implemented within many othernetwork environments. For example, the invention can be implementedadvantageously in purely-wireline network environments, i.e., in networkenvironments which do not included a wireless network or wireless(mobile) devices.

III. WSDK Server Framework (WSF)

[0088]FIG. 4A shows the key classes/objects in the WSF 3 and thehigh-level relationships (control flow) between them. The classesinclude: OipsCallMgr, OipsCallResources, OipsServiceMgr, OipsCallCtxt,and OipsOpCtxt. OipsCallResources has a subclass OipsTxnCtxt, which hasa subclass OipsTxnMember. OipsServiceMgr has a subclass OipsService,which has a subclass OipsOperations. OipsOpCtxt has subclassesOipsOpSummary and OipsStatus.

[0089] Following each class name in FIG. 4A are three additional itemsof information (in the following order):

[0090] The number of subclasses of the given class that may exist. Ifthe number is 0, the class may not be subclassed. For both subclass andobject cardinality, “n” and “m” mean “any number”.

[0091] The number of instances (objects) of that class, relative to theenclosing object. If a class is an abstract parent class (listed initalics), then this refers to the number of instances of each subclass.Otherwise, it is the number of objects of the listed class.

[0092] The lifetime of objects of that class.

[0093] There are three possible lifetimes of an object: server, call,and txn. Objects with “server” lifetime are created and initializedduring server initialization and exist for the lifetime of the server.Objects with “call” lifetime are created and initialized when a newrequest message is received by the call manager and exist until thereply message has been generated. Objects with “txn” lifetime arecreated and initialized at the beginning of a logical transaction.Depending upon the error handling method identified in the requestmessage, a transaction will either span an entire call or just theexecution of a single operation (for calls that contain only oneoperation request, this distinction is moot).

[0094] The roles of the key classes/objects of the WSF 3 will now bedescribed. The OipsCallMgr object coordinates the call dispatch process.This object is responsible for initializing the call context andresources, for dispatching the operation executions, and for all majorerror handling and transaction management logic. The OipsCallMgr is aconcrete class (no subclassing) with a single instance that exists forthe lifetime of the server. The functionality of this class is describedfurther below.

[0095] The OipsCallResources object is a holder for call-relatedresources that do not directly correspond to items in the request orreply messages.

[0096] The OipsTxnCtxt object contains a list of members (instances ofsubclasses of OipsTxnMember) of the current transaction and delegatescommit( ) and rollback( ) methods to those objects.

[0097] The OipsCallCtxt object contains the parsed request message andpartially generated reply message for the current call and providesmethods for traversing the request and populating the reply. This classis the server-side equivalent to “OipcCall” on the client side (seedescription of WCAF, below). Hence, OipsCallCtxt includes:

[0098] requestDoc (OipmInputDoc)—the parsed request received from theclient

[0099] replyDoc (OipmOutputDoc)—the reply document sent (or will send,when it is completed) to the client.

[0100] errorMode (enum OipcErrorMode)—the indication of the error modeto be used (e.g., “stop”, “continue”, or “rollback”) when executing theoperations in a request. In “stop” mode, execution of the operations forthe request is stopped in response to an error occurring duringexecution of the operations. In “continue” mode, execution of theoperations for the request continues in response to an error occurringduring execution of the operations. In “rollback” mode, execution of theoperations for the request is stopped in response to an error occurringduring execution of the operations, and the state that existedimmediately prior to execution of the first operation for the request isresumed.

[0101] The OipsServiceMgr object is responsible for loading serviceimplementations (during server initialization) and for providing accessto service operations (during request processing).

[0102] The OipsService class is an abstract parent class. Eachimplemented service will have one subclass of OipsService and oneinstance of that subclass. Service classes are primarily responsible forinitializing operations (during server initialization) and for providingaccess to operations (during request processing). Service classskeletons are generated by OSDGen 1. In many cases, the generated codeis sufficient.

[0103] The OipsOperation class is an abstract parent class. Eachimplemented operation will have one subclass of OipsOperation and oneinstance of that subclass. Operation class skeletons are generated byOSDGen 1 and contain an execute( ) method that is invoked by theOipsCallMgr object to execute a particular operation. Many subclasses ofthe OipsOperation class may exist. For each subclass, there is exactlyone instance that exists for the lifetime of the server.

[0104] The OipsOpCtxt class is an abstract parent class that containsthe “request” and “reply” fragments for each operation found in therequest. OipsOpCtxt is equivalent to “OipcOperation” on the client side.Each implemented operation will have one subclass of OipsOpCtxt.Instances of these subclasses are created as necessary (by theOipsCallMgr object via delegation through the OipsServiceMgr object) tohold the data contained in the current request. Operation contextclasses are fully generated by OSDGen 1 and do not require any manualcoding. OipsOpCtxt contains the following standard methods:

[0105] parseRequest( )—similar to “docToReply” function ofOipcOperation. This populates the “request” portion of the operationcontext from data parsed from the requestDoc of the call context.

[0106] writeReply( )—similar to “requestToDoc” function ofOipcOperation. This writes the “reply” data from the operation contextinto the replyDoc of the call context.

[0107] OipsOpSummary objects contain the set of information that will belogged in the operation summary logs for the execution of the associatedoperation. There is a standard set of information provided automaticallyby WSF. Individual operations can augment this information by addingadditional parameters (with names of the form “x-name”).

[0108] OipsStatus objects are used for reporting application faults. Astandalone OipsStatus population function is automatically generated byOSDGen 1 for each faultdef defined for a service.

[0109] The objects and processes used on the server side are describedfurther below.

IV. WSDK Client API Framework (WCAF)

[0110] The WCAF 2 will now be described with reference to FIG. 4B. Inthe illustrated embodiment, the WCAF 2 includes two data structures 41,named OipcOperation and OipcCall, and a set of functions 42, namedoipclnitCall, oipcAddOperation, oipcGenerateRequest, and oipcSetReply.

[0111] The OipcOperation data structure represents an instance of aparticular operation. This structure is utilized in a manner similar toa C++ abstract class—it defines a set of standard attributes andfunction pointers. Actual operations have their own unique structuretypes (but may be “casted” to OipcOperation). The OipcOperationstructure contains the following:

[0112] requestToDoc(OipcCall*, OipcOperation*)—write the request datafrom the operation into the “output document” of the OipcCall.

[0113] docToReply(OipcCall*, OipcOperation*)—read from the “inputdocument” of the OipcCall and write to the “reply” portion of theoperation.

[0114] cleanup(OipcOperation*)—clean up any memory allocated by“docToReply”.

[0115] Each “derived” OipcOperation structure also contains a “request”structure and a “reply” structure.

[0116] The OipcCall structure contains the contents of an entire messageexchange between client and server, i.e.:

[0117] requestHeader (struct OipcRequestHeader)—a simple structurecontaining standardized request message header information (mostlyclient identification information used for logging).

[0118] replyHeader (struct OipcReplyHeader)—a simple structurecontaining standardized reply message header information (mostly serveridentification information).

[0119] ops (OipcOperation*[ ])—an array of “OipcOperation” structures.

[0120] markupStyle (enum OipmMarkupStyle)—the markup “style” used forthis call (e.g., Lite, SOAP). A markup style corresponds to a markuplanguage. It includes an enumerated type and an associated markupimplementation (a software module) that handles conversion between the“generic” data format and a markup language-specific data format.

[0121] errorMode (enum OipcErrorMode)—the error mode the server shoulduse when executing the request (continue, stop, or rollback).

[0122] requestDoc (OipmOutputDoc)—the request document created when the“requestToDoc” functions for all the operations in “ops” are called.

[0123] replyDoc (OipmInputDoc)—the reply document parsed from the replybuffer received from the server.

[0124] The functions included in the WCAF 2 are oipclnitCall,oipcAddOperation, oipcGenerateRequest, and oipcSetReply. These functionsare defined as follows:

[0125] oipcInitCall(OipcCall*,OipmMarkupStyle,OipcErrorMode)—initializea new call

[0126] oipcAddOperation(OipcCall*,OipcOperation*)—Add an operation tothis call (the “request” portion of the operation structure should befilled out before calling this function).

[0127] oipcGenerateRequest(OipcCall*, char**, unsigned*)—Finalize therequest message and return it as a text buffer for submitting to theserver (calls the “requestToDoc” functions for each operation in thecall).

[0128] oipcSetReply(OipcCall*, char*, unsigned)—Parse the given replybuffer received from the server and use it to populate the reply part ofeach of the call's operations (calls the “replyToDoc” functions for eachoperation in the call).

[0129] As can be seen from the foregoing description, the WCAF 2 hascomponents that mirror the functionality of the server side, but withsome important differences. On the client side, a call is created fromscratch. Separately, operations are created from scratch, their requestportions are populated, and they are added to the call. The call is thenserialized into a request message and sent to the server. The resultingreply message is parsed and used to populate the “reply” portions ofeach of the operations.

[0130] In contrast, on the server side, a call is initialized with theincoming request document. No operation structures are contained withinthe call structure. Instead, operation structures are created as therequest document is parsed and the reply document is written.

V. WSDK Library

[0131] The WSDK Library 4 (also called the “markup engine” or “markuplibrary”) has two modules: an input module 51 and an output module 52,as shown in FIG. 5. Before examining these two modules in detail,however, note first that there are three principals in the markupspace: 1) the “core” markup library; 2) markup implementations(described below); and 3) users of the markup library. Between thesethree principals, there are four distinct visibility relationships, thatapply to both the input module 51 and the output module 52:

[0132] The core markup library exports public data structures(“core-public-data”) for use by both users of the markup library andmarkup implementations.

[0133] The core markup library exports a public interface(“core-public-func”) for use by users of the markup library.

[0134] The core markup library exports a private interface(“core-private”) for use by markup implementations (“core-private”).

[0135] Markup implementations export private interfaces(“markup-private”) for use by the core markup library(“markup-private”).

[0136] The above topology applies to both the input module 51 and theoutput module 52 of the WSDK Library 4.

[0137] A. Input Module

[0138] In accordance with one embodiment of the invention, the inputmodule 51 includes the following elements:

[0139] A single complex (core-public-data) data structure, calledOipmlnputDoc, used by both markup library users and markupimplementations.

[0140] A set of (core-public-func) functions for “reading” the datastructure, used by markup library users.

[0141] A set of (core-private) functions for “writing” the datastructure, used by markup implementations.

[0142] A single (core-public-func) function for “creating” the datastructure, used by markup library users. For each markup implementation,there is a single (markup-private) function that is invoked from thecore-public-func function. This markup-private function uses thecore-private functions to construct the OipmlnputDoc.

[0143] A single (core-public-func) function for “destroying” the datastructure, used by markup library users.

[0144] Thus, the input module 51 is illustrated conceptually in FIG. 6,according to one embodiment. As shown, the input module 51 includes thedata structure 61, called OipmInputDoc (core-public-data), a submodule62 (core-public-func) that handles the lifecycle and navigation of theinput parse tree, a submodule 64 (core-private) that handlesconstruction of the input parse tree, and a set of input markupimplementations 63 (markup-private).

[0145] The OipmInputDoc data structure 61 is a complex data structurethat is used by both markup library users and markup implementations 63.It includes the following fields: 1) a “markup style” (i.e., anenumerated type defined as part of (core-public-date) and an associatedmarkup implementation 63 that handles converting between the “generic”data format and a markup language-specific data format); 2) a referenceto the raw text buffer that was used to construct the input document(this buffer is modified as the document is parsed); 3) an array of“entries”; 4) an array of entry “entry arrays”; and 5) a “current group”context. The “markup style” indicates the markup style that is in effectfor the document.

[0146] An “entry” represents an entity found while parsing the document.There are two basic types of entries (indicated with a Boolean flag): an“item” entry and a “group” entry. An “item” entry has a single valueassociated with it. A “group” entry, which has a list of “child” entryarrays associated with it (see below). The parent-child relationshipbetween groups and their sub-entries directly corresponds to the typicalhierarchy one observes from structured documents. Consider the followingexample: <foo> <bar1>value1</bar1> <bar2>value2</bar2> </foo>

[0147] In this case, the group “foo” has two children (bar1 and bar2).

[0148] An entry array provides a mechanism for aggregating multipleentries with the same name. Entry arrays have a “name” and one or morechild entries (the child entries may be items or groups). Theparent-child relationship between entry arrays and entries is nottypically apparent from an examination of original document—it is anartifact of the implementation to support asking for entries by name andindex.

[0149] Consider the following document fragment: <foo> <bar>bar value1</bar> <bar>bar value 2</bar> <fubar>fubar value</fubar> </foo>

[0150] This write in would be represented in the parse tree asfollows: * Entry array with name “foo” * Group entry (index 0) * Entryarray (index 0) with name “bar” * Item entry (index 0) with value “barvalue 1” * Item entry (index 1) with value “bar value 2” * Entry array(index 1) with name “fubar” * Item entry at index 0 with value “fubarvalue”

[0151] As noted above, the input module 51 of the markup library 4includes a submodule 62 (core-public-func) that handles the lifecycleand navigation of the input parse tree, and a set of markupimplementations 63. A set of key functions for operating on the inputdocument form at least a portion of submodule 62 and markupimplementations 63. These functions, according to one embodiment, arenamed: oipmInitInputDoc, oipmNumEntries, oipmOpenGroup, oipmGet*(where“*” represents one of several possible suffixes), andoipmCloseGroup, and are characterized as follows:

[0152] oipmInitInputDoc(IN inputDoc, IN buffer, IN markupStyle)—thisfunction inputs a text buffer and a markup style (how the text buffershould be interpreted). The function is called with an empty parse tree(no entries or entry arrays). When it returns, the parse tree is fullypopulated. All of the other input functions operate on the parse tree,not on the original text buffer. Documents have a single top-level groupand the “current group” is set to this top-level group.

[0153] Note that documents written in any markup language (withinreasonable bounds) can be converted into a standardized parse tree—thusdocument navigation is fully insulated against differences in markuplanguages. Note also that for purposes of this document, for ease ofreference, different versions or variations of a given markup languageshall be treated as different markup languages.

[0154] oipmNumEntries(IN inputDoc, IN name, OUT count)—This functionlooks for an entry array within the current group with the given nameand then returns the number of child entries for that array. If no arrayis found with the given name or it contains no entries, 0 is returned.

[0155] oipmOpenGroup(IN inputDoc, IN name, IN index)—This function looks(within the current group) for an entry array with the given name and anentry with the given index within that array, checks to see if thatentry is a group, and if so, changes the “current group” context to thatgroup.

[0156] oipmGet*(IN inputDoc, IN name, IN index, OUT value)—Thesefunctions (oipmGetData, oipmGetlnt, and oipmGetString) look for an entryarray (within the current group) with the given name and a child withthe given index and returns the value associated with that child entry.

[0157] oipmCloseGroup(IN inputDoc)—This function switches “currentgroup” to the parent of the current group (the parent of the arraywithin which the current group is located). Equivalent to a “cd . . . ”in a UNIX shell.

[0158] Submodule 64 (core-private) includes a set of implementation“helper” functions that are used by markup implementations to build theparse tree. These helper functions, according to one embodiment, arenamed: oipmiAddArray, oipmiAddEntry, oipmiGetArray, oipmiGetEntry,oipmiNewArray, and oipmiNewEntry, and are characterized as follows:

[0159] oipmiAddArray (IN inputDoc, IN groupEntry, IN entryArray)—addsthe given array as a child of the given group entry.

[0160] oipmiAddEntry (IN inputDoc, IN entryArray, IN entry)—adds thegiven entry as a child of the given entry array.

[0161] oipmiGetArray(IN inputDoc, IN name, OUT entryArray)—returns theentry array with the given name within the current group.

[0162] oipmiGetEntry(IN inputDoc, IN name, IN index, OUT entry)—returnsthe entry at position “index” within the array named “name” found withinthe current group.

[0163] oipmiNewArray(IN inputDoc, OUT entryArray)—returns a newlyinitialized entry array

[0164] oipmiNewEntry(IN inputDoc, OUT entry)—returns a newly initializedentry.

[0165] The input module 51 also includes a set of input markupimplementations 63, as noted above. Each markup style has an associatedinput markup implementation. When “oipmInitInputDoc” is called, themarkup library calls the appropriate markup implementation, based uponthe markup style selected. The markup implementations are expected toparse through the original input buffer (possibly modifying it) and usethe helper functions described above to construct the input documentparse tree.

[0166] Note that the markup implementations 63 and the implementationhelper functions are not visible to users of the WSDK Library 4—they areartifacts of markup language implementation.

[0167] B. Output Module

[0168] The output module 52 of the markup library 4 is based on asimilar principle to that of the input module 51 (i.e., users of thelibrary construct documents via a standardized logical model withoutregard to markup-language specific issues) but has a differentimplementation. A strict inversion of the input module would involvecreating a parse tree via a set of markup-neutral API functions,followed by a markup-specific translation of that parse tree to a textbuffer. For performance reasons, however, only a very sparse amount ofcontext information is maintained and the output document is mostlybuilt on the fly.

[0169] The output module 52 has a structure similar to that of the inputmodule 51 represented in FIG. 6. In particular, the output module 52includes:

[0170] A single complex (core-public-data) data structure, calledOipmOutputDoc, used by both markup library users and markupimplementations.

[0171] A set of (core-public-func) functions for “writing” the datastructure, used by markup library users. For each markup implementation,there is a (markup-private) function that corresponds to (almost every)core-public-func function.

[0172] A single (core-public-func) function for “initializing” the datastructure, used by markup library users. For each markup implementation,there is a (markup-private) function that corresponds to thisinitialization function. These markup-private functions typically havevery little functionality.

[0173] A set of (core-private) functions for “writing” the datastructure, used by markup implementations.

[0174] The data structure OipmOutputDoc represents the document underconstruction. Key fields of this structure include: 1) A markup style,2) a group “stack”; and 3) the output buffer under construction. Thegroup “stack” is used to capture the context for the output document.For example, suppose we were at the following location in a document:<group1> <blah>blahblah</blah> <group2> <blah>blahblah</blah> <group3><-- we're here

[0175] In this case, the group stack would contain:

[0176] group1

[0177] group2

[0178] group3<−−top of stack

[0179] Similarly to the input module 51, the output module 52 includes aset of key functions for operating on output documents, which accordingto one embodiment are: oipmInitOutputDoc, oipmBeginGroup, oipmEndGroup,and oipmput* (where“*” represents one of several possible suffixes).These functions are characterized as follows:

[0180] oipmInitOutputDoc(IN outputDoc, IN markupStyle)—initializes thedocument appropriately for the given markup style. Note that thisfunction provides much less functionality than its counterpart in theinput module 51, oipmInitInputDoc.

[0181] oipmBeginGroup(IN outputDoc, IN name)—open up a group with thegiven name within the current context (and add the new group name to thetop of the group stack). For a markup language based on XML, this wouldtypically involve writing the group name within < >, e.g.:

[0182] oipmBeginGroup(odoc, “foo”)

[0183] would add “<foo>” to the output document.

[0184] oipmEndGroup(IN outputDoc)—close the current group and remove itfrom the top of the group stack. For a markup language based upon XML,this would typically involve writing a close tag for the group, e.g.:

[0185] oipmBeginGroup(odoc, “foo1”);

[0186] oipmBeginGroup(odoc, “foo2”);

[0187] oipmEndGroup(odoc);

[0188] oipmEndGroup(odoc);

[0189] might result in: <foo1> <foo2> </foo2> </foo1>

[0190] oipmPut*(IN outputDoc, IN name, IN value)—write an item of theappropriate type (oipmPutData, oipmPutlnt, oipmPutString) into thedocument, e.g.:

[0191] oipmBeginGroup(odoc, “group1”);

[0192] oipmPutString(odoc, “foo”, “foo_value”);

[0193] oipmBeginGroup(odoc, “group2”);

[0194] oipmPutlnt(odoc, “ifoo”, 10);

[0195] oipmEndGroup(odoc);

[0196] oipmEndGroup(odoc);

[0197] might result in something like: <group1> <foo>foo_value</foo><group2> <ifoo>10</ifoo> <group2> <group1>

[0198] An implementation helper function in the output module 52reserves space in the output buffer prior to writing to it. Thisfunction, oipmiReserveOutput, is defined as follows:

[0199] oipmiReserveOutput(IN outputDoc, IN bytesNeeded)

[0200] The output module 52 also contains a set of output markupimplementations, as noted above. Input markup implementations 63 includea single function that is called from oipmInitInputDoc. Output markupimplementations, however, include a set of functions to accomplish eachof the following actions:

[0201] Initializing the output buffer

[0202] Beginning a group

[0203] Ending a group

[0204] Writing a data buffer

[0205] Writing an integer

[0206] Writing a string

[0207] Finalizing an output buffer

[0208] When the corresponding API function is called by a user of themarkup library API, that function in turn calls the appropriateimplementation function (based upon the markup style registered for thedocument).

[0209] C Header Files

[0210] In one embodiment of the invention, the above-described datastructures and key functions for both the input module 51 and the outputmodule 52 are all declared in a single C header file. The implementationhelper functions are declared in a separate header file (for use bymarkup implementers).

[0211] In one embodiment, these header files are named oip_markup.h,oip_markup_impl.h, oipm_light.h and oipm_soap.h, and are defined asfollows:

[0212] oip_markup.h: Contains definitions for OipmInputDoc,OipmOutputDoc, and public oipm* functions. Used by programmers who codeto a WSDK-based client API.

[0213] oip_markup_impl.h: Contains declarations for all oipmi*functions. Used by markup implementors.

[0214] oipm_light.h: Contains declarations for the “Lite” markup. Usedby markup library.

[0215] oipm_soap.h: Contains declarations for the “SOAP” markup. Used bymarkup library.

[0216] D. Markup Implementations

[0217] In one embodiment of the invention, the WSDK library includesmarkup implementations to support at least two markups, SOAP andOIP-LIGHT.

[0218] 1. OIP-LITE Markup Implementation

[0219] The OIP-LITE markup language has a simple syntax. Groups entriesare represented as: groupName ( )

[0220] Item entries use a simple run-length encoding mechanism forvalues:

[0221] FirstName 6

[0222] Andrew

[0223] (In this case “6” is the length of the value “Andrew” associatedwith the entry named “FirstName”).

[0224] For example:

[0225] oipminitOutputDoc(odoc, eOipmLITE);

[0226] oipmBeginGroup(odoc, “Person”);

[0227] oipmPutString(odoc, “FirstName”, “Andrew”);

[0228] oipmPutString(odoc, “LastName”, “Large”);

[0229] oipmPutInt(odoc, “Age”, 36);

[0230] oipmEndGroup(odoc);

[0231] oipmFinalizeOutput(odoc, buf);

[0232] would result in a buffer that contains: Envelope ( Person (FirstName 6 Andrew LastName 5 Large Age 2 36 ) )

[0233] When parsed into an input document, you would have: array“Envelope” entry (group) 0 array “Person” entry (group) 0 array“FirstName” entry (item) 0, value “Andrew” array “LastName” entry (item)0, value “Large” array “Age” entry (item) 0, value “36”

[0234] 2. SOAP Markup Implementation

[0235] The SOAP implementation can be simply an XML parser generatorwith some hard-coded conventions around special elements, including theSOAP “envelope”, “header”, and “body” groups. For example:

[0236] oipmInitOutputDoc(odoc, eOipmSOAP);

[0237] oipmBeginGroup(odoc, “Person”);

[0238] oipmPutString(odoc, “FirstName”, “Andrew”);

[0239] oipmPutString(odoc, “LastName”, “Large”);

[0240] oipmPutInt(odoc, “Age”, 36);

[0241] oipmEndGroup(odoc);

[0242] oipmFinalizeOutput(odoc, buf);

[0243] would result in: <SOAP-ENV:Envelope xmlns:SOAP-ENV=“http://schemas.xmlsoap.org/soap/envelope/”> <SOAP-ENV:Body><oip:envelope xmlns:oip=“http://www.openwave.com/protocols/oip/”><oip:Person> <oip:FirstName>Andrew</oip:FirstName><oip:LastName>Large</oip:LastName> <oip:Age>10</oip:Age> </oip:Person></oip:envelope> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

[0244] and would have exactly the same parse tree structure as the“LITE” version for the input document.

[0245] In one embodiment of the invention, the SOAP markupimplementation includes the following functions and operates asdescribed:

[0246] oipmsParseDoc( )—this is called from oipmInitInputDoc when themarkup style is SOAP. Its role is to parse through a buffer containingSOAP/XML markup and build the corresponding parse tree. Consider thefollowing document: <SOAP-ENV:Envelope . . . > <SOAP-ENV:Body><oip:envelope . . . > <oip:AuthUser> <oip:userName>user</oip:userName><oip:password>password</oip:password> </oip:AuthUser> </oip:envelope></SOAP-ENV:Body> </SOAP-ENV:Envelope>

[0247] The function would skip over the SOAP-ENV tags to find the“oip:envelope” tag, and then:

[0248] When it found the opening “oip:envelope” tag, it would call:

[0249] oipmiNewEntry( )—to create an entry for the envelope group

[0250] oipmiNewArray( )—to create an array for the envelope group

[0251] oipmiAddEntry( )—to add the envelope entry to the envelope array.

[0252] and then set the newly created entry as the current group.

[0253] When it found the “oip:AuthUser” tag, it would call:

[0254] oipmiNewEntry( )—to create an entry for the AuthUser group

[0255] oipmiNewArray( )—to create an array for the AuthUser group

[0256] oipmiAddArray( )—to add the AuthUser array to the envelope group

[0257] oipmiAddEntry( )—to add the AuthUser entry to the AuthUser array

[0258] and then set the newly created entry as the current group.

[0259] When it found the “oip:userName” tag, it would call:

[0260] oipmiNewEntry( )—to create an entry for the userName item

[0261] oipmiNewArray( )—to create an array for the userName item

[0262] oipmiAddArray( )—to add the userName array to the AuthUser group

[0263] oipmiAddEntry( )—to add the userName entry to the username array

[0264] When it found the “user” text for the oip:userName tag, it wouldchange the entry type to ITEM, set the value to point to where “user”occurred in the text buffer, and skip past the “/oip:userName” closingtag.

[0265] When it found the “oip:password” tag it would call:

[0266] oipmiNewEntry( )—to create an entry for the password item

[0267] oipmiNewArray( )—to create an array for the password item

[0268] oipmiAddArray( )—to add the password array to the AuthUser group

[0269] oipmiAddEntry( )—to add the password entry to the username array

[0270] When it found the “password” text for the oip:password tag, itwould change the entry type to ITEM, set the value to point to where“password” occurred in the text buffer, and skip past the“/oip:password” closing tag.

[0271] When it found the “/oip:AuthUser” closing tag, it would changethe current group to the parent of the AuthUser array (the envelopegroup).

[0272] When it found the “/oip:envelope” closing tag, it would changethe current group to the parent of the envelope array (the top contextof the document).

[0273] oipmsBeginGroup—called from oipmBeginGroup when the markup styleis SOAP. Example:

[0274] oipmsBeginGroup(doc, “AuthUser”)

[0275] would call:

[0276] oipmsReserveOutput(doc, 15);

[0277] oipmiOutputData(doc, “<oip:AuthUser>\n”);

[0278] and then push “AuthUser” onto the output group stack.

[0279] oipmsEndGroup—called from oipmEndGroup when the markup style isSOAP. Example:

[0280] oipmsEndGroup(doc)

[0281] would call:

[0282] oipmiReserveOutput(doc, 16);

[0283] oipmiOutputData(doc, “</oip:AuthUser>\n”);

[0284] and then pop “AuthUser” off the output group stack.

[0285] oipmsFinalize—called from oipmFinalizeOutput when the markupstyle is SOAP. This just adds the SOAP closing tags to the document,e.g.:

[0286] static const char*soapTrailer=“</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\n”;

[0287] oipmiReserveOutput(doc, strlen(soapTrailer));

[0288] oipmiOutputData(doc, soapTrailer);

[0289] oipmsInitDoc—called from oipmInitOutputDoc when the markup styleis SOAP. This just adds the SOAP header tags to the document, e.g.:

[0290] static const char*soapHeader=“<SOAP-ENV:Envelope>\n<SOAP-ENV:Body>\n”;

[0291] oipmiReserveOutput(doc, strlen(soapHeader));

[0292] oipmiOutputData(doc, soapHeader);

[0293] oipmsPutData—called from oipmPutData when the markup style isSOAP. This encodes the data in base64 and then writes the data to thedocument, e.g.:

[0294] char encodedBuffer[ ];

[0295] base64Encode(buffer, encodedbuffer);

[0296] oipmiReserveOutput(doc,strlen(encodedBuffer)+(strlen(name)+7)*2);

[0297] oipmiOutputData(doc, “<oip:”);

[0298] oipmiOutputData(doc, name);

[0299] oipmiOutputData(doc, “>”);

[0300] oipmiOutputData(doc, encodedBuffer);

[0301] oipmiOutputData(doc, “</oip:”);

[0302] oipmiOutputData(doc, name);

[0303] oipmiOutputData(doc, “>”);

[0304] oipmsPutString—called from oipmPutString when the markup style isSOAP, e.g.:

[0305] oipmiReserveOutput(doc, strlen(buffer)+(strlen(name)+7)* 2);

[0306] oipmiOutputData(doc, “<oip:”);

[0307] oipmiOutputData(doc, name);

[0308] oipmiOutputData(doc, “>”);

[0309] oipmiOutputData(doc, buffer);

[0310] oipmiOutputData(doc, “</oip:”);

[0311] oipmiOutputData(doc, name);

[0312] oipmiOutputData(doc, “>”);

VI. OSD and OSDGen

[0313] Development of a WSDK-based service starts with OperationStructure Definition (OSD) specifications for the service. OSD is ahierarchical declaration language with a lexical syntax somewhat similarto LISP. Fundamentally, OSD is a language for describing the logicalstructure of operation requests and replies. The structure declaredwithin an OSD file directly maps to markup API calls described above. Inother words, OSD is used to describe the interface to a set ofoperations (similar to the logical section of a WSDL description) and tointroduce additional server-side authorization and validation logic.

[0314] Programmers will manually construct OSD files during development.They will then use OSDGen 1 during development to create skeletonserver-side operation implementations (in, for example, C++ or Java),which they then manually populate with the code that handles executingthe operation.

[0315] During build (when source code is translated to binary), OSDGen 1is used to generate the entire service client API, as well as portionsof the server-side code (the context classes). The generated code isgenerated and compiled in a single logical build step.

[0316] OSDGen 1 is not used at runtime. However, both the code generatedby OSDGen 1 (the client API and the server-side operation context code)and the manually written server-side operation implementation are used.

[0317] The primary entities defined using OSD include:

[0318] service. This is the primary top-level entity in an OSD file. Aservice has a set of attributes (including name, version number,description, etc.) as well as a number of sub-entities. Sub-entities ofservice include itemdef, groupdef,faultdef, and operation.

[0319] itemdef. Itemdefs are used for defining simple types. In additionto a name, they have a corresponding markup type (e.g., string, integer,etc.) and a set of validation rules (min/max value, regular expression,etc.).

[0320] groupdef. Groupdefs are used for defining complex “struct”-styletypes. In addition to a name, they contain a combination of items andgroups:

[0321] item. Items represent simple name/value pairs. In addition to aname, they have an associated itemdef or markup type, a cardinalityclause, and a default value.

[0322] group. Groups represent complex name/value pairs. In addition toa name, they have an associated groupdef and a cardinality clause.

[0323] faultdef. Faultdefs are used for defining a service-specificfault that may be returned from an operation defined within the service.Faultdefs contain a name, a numeric code, and a message format string(similar to a printf string, but with argument names as well).

[0324] operation. Operations represent the individual tasks that aservice can execute. Operations have a set of attributes (includingname, version number, description, etc.) as well as sub-entities.

[0325] request. A request defines the structure of the informationprovided in a request for execution. Structurally, it is equivalent to agroupdef with no name.

[0326] reply. A reply defines the structure of the information providedin a reply provided with an operation execution. Structurally, it isequivalent to a groupdef with no name.

[0327] fault. This is used to identify that a particular fault(identified byfaultdef name) may be returned by this operation.

[0328] OSD also supports the equivalent of the C pre-processor“#include” directive.

[0329] The most common organization of OSD files includes: a singletop-level service file; a file that contains all the itemdef, groupdef,and faultdef definitions for the service; and a separate file for eachoperation.

[0330] Once OSD files exist, OSDGen 1 can be used to generate thefollowing types of service-specific source files (based uponcommand-line options to OSDGen 1), server-side operation classes,server-side operation context classes, server-side service facilityclasses, client-side operation context code, and client-side supportfiles:

[0331] Server-side operation classes. For each defined operation thatdoes not have an associated C++ class, one will be generated for it. Thegenerated classes inherit from the OipsOperation class and contain amethod called execute( ). This method is invoked (with appropriateparameters) when execution is requested for that operation.

[0332] Server-side operation context classes. For each definedoperation, a C++ context class will be generated. Operation contextclasses inherit from OipsOpCtxt and contain request and reply data for aparticular instance of an operation execution and logic forserializing/deserializing operation request and reply data.

[0333] Server-side service facility classes. For each service, a smallset of additional C++ classes are generated. These include a top-levelclass derived from OipsService (includes service-initialization andoperation registration logic) as well as classes that defineservice-specific types and itemdef-specific validation logic.

[0334] Client-side operation context code. For each operation, a“struct” declaration and associated functions is generated. This code isdesigned to plug into the WCAF 2 and is similar to the server-sideoperation context classes, with the exception that it lacks the richvalidation and version mapping logic found in the server-side classesand is written in C instead of C++.

[0335] Client-side support files. These files include both WSDLspecifications for the service and fault message catalogs (in catgetsformat, to enable localization of fault messages).

[0336] 2. OSD Details

[0337] OSD has a grammar that maps to the markup language structure.There are two types of “entries” in OSD: a “group” entry and an “item”entry. A group entry in OSD is depicted as:

[0338] (type “name”. . . )

[0339] An “item entry” in OSD is depicted as:

[0340] name “value”

[0341] The following main groups are defined within OSD: service,itemdef, item, groupdef, group, operation, which are characterized asfollows:

[0342] service—used to define services. This is the highest-levelconstruct in OSD. Everything else falls within a service definition,e.g.:

[0343] (service “smg”

[0344] . . .

[0345] )

[0346] itemdef—used to define types for items that will be contained ina request or reply, e.g.: (itemdef “OipAuthToken” mtype “string” #markup type (string, int, or data) min_length “64” max_length “64”)

[0347] item—an instance of an item, e.g.: (item “authToken” type“OipAuthToken” card “1 . . . 1”)

[0348] groupdef—used to define (complex) types for groups that will becontained in a request or reply, e.g.: (groupdef “Subscriber” (item “id”type “SmgSubscriberId” card “1 . . . 1”) (item “authToken” type“OipAuthToken” card “1 . . . 1”) (group “attrs” type “Attribute” card “0. . . n”) )

[0349] group—used to define an instance of a group

[0350] operation—used to define an operation. Every operation mustcontain a “request” and a “reply” group: (operation“AuthenticateSubscriber” (group “request” (group “lookupInfo” type“LookupInfo” desc “Information to find the subscriber.” card “1 . . .1”) (group “authInfo” type “AuthInfo” desc “Information to authenticatethe subscriber.” card “1 . . . 1”) ) (group “reply” (item “id” type“SmgSubscriberID” card “1 . . . 1” write_ctxt “true” desc “Globallyunique subscriber ID”) (item “authToken” type “OipAuthToken” card “1 . .. 1” write_ctxt “true” desc “To be used with future requests.”) ) )

[0351] Consider the following trivial example of a service that containsan operation for translating from a numerical digit to the correspondingEnglish word (e.g., “1”->“one”). (service “digit” (itemdef “DigitWord”mtype “string” min_length “3” max_length “5”) (itemdef “DigitSymbol”mtype “integer” min “0” max “9”) (operation “ToWord” (group “request”(item “symbol” type “DigitSymbol” card “1 . . . 1”)) (group “reply”(item “word” type “DigitWord” card “1 . . . 1”)) ) )

[0352] On the client side, OSDGen 1 would produce the following set of Cdeclarations: struct DigitToWordRequest { int symbol; }; structDigitToWordReply { char* word; }; struct DigitToWordOperation {OipcStatus (*requestToDoc)( OipcCall* call, const OipcOperation* op);OipcStatus (*docToReply)( OipcCall* call, OipcOperation* op); void(*cleanup)( OipcOperation* op); DigitToWordRequest request;DigitToWordReply reply; 56 ;

[0353] extern void digitlnitToWord(DigitToWordOperation*);

[0354] The following is an example of what the init and “requestToDoc”functions for DigitToWordOperation would look like: voiddigitInitToWord( DigitToWordOperation* op) { memset(op, 0,sizeof(DigitToWordOperation)); op->cleanup =_DigitToWordCleanup;op->docToReply =_DigitToWordDocToReply; op->requestToDoc=_DigitToWordRequestToDoc; } static OipsStatus_DigitToWordRequestToDoc(OipcCall* call, const OipcOperation* op) { const DigitToWordOperation*1_op = (const DigitToWordOperation*)op; const DigitToWordRequest* r =&1_op->request; oipmBeginGroup(&call->requestDoc, “digit_ToWord”);oipmPutInt(&call->requestDoc, “symbol”, r->symbol);oipmEndGroup(&call->requestDoc); }

[0355] Server-Side Context:

[0356] If a reply item is marked with ‘write_ctxt “true”’, then theserver will write the reply data for that item in two locations withinthe OipsCallCtxt object: 1) in the reply document (using the same oipm*functions displayed above for the client); and 2) in a context “map”maintained within the call context (see below). If a request item ismarked with ‘read_ctxt “true”’, then a query for that item in therequest will look in two places: 1) in the request document (via theappropriate oipmGet* function); and 2) if it is not found in the requestdocument, then the context map is queried for the item.

[0357] This relationship between write_ctxt and read_ctxt is animportant facet of the batching capabilities of the server, since itallows for a batch in circumstances that might normally require anadditional round-trip. In particular, one can specify that reply(output) data from one operation in a batch be used as request data(input) for a later operation in the same batch. For example, considerthe following:

[0358] Operation AuthUser

[0359] request=user name and password

[0360] reply=authentication token

[0361] Operation GetUserProfile

[0362] request=authentication token

[0363] reply=profile

[0364] Marking the authentication token in the reply of AuthUser as‘write_ctxt “true”’ and the authentication token in the request ofGetUserProfile allows for both of these operations to be submitted aspart of the same batch (essentially using output from AuthUser as inputto GetUserProfile).

[0365] As an example of how OSDGen 1 parses OSD files, consider thefollowing simple example OSD code fragment: (groupdef “Person” (item“FirstName” mtype “string”) (item “LastName” mtype “string”) (item “Age”mtype “int” min “1” max “200”) ) (operation “PromoteEmployee” (request(group “person” type “Person”)) . . . )

[0366] The above OSD fragment says that a “PromoteEmployee” operationexpects to have a “Person” identified in the request. OSDGen 1 parsesthese structural definitions and automatically generates the code thatactually invokes the WSDK library API. So, for the above operation,client code would be automatically generated by OSDGen 1 to contain thefollowing code fragment in the portion of the “PromoteEmployee” clientAPI that is responsible for generating the request message:

[0367] . . .

[0368] oipmBeginGroup(odoc, “Person”);

[0369] oipmPutString(odoc, “FirstName”, request.FirstName);

[0370] oipmPutString(odoc, “LastName”, request.LastName);

[0371] oipmPutString(odoc, “Age”, request.Age);

[0372] oipmEndGroup(odoc);

[0373] . . .

VII. System Operation

[0374] A. System Initialization

[0375] System initialization begins with the initialization ofserver-level resources (logging, configuration, etc.) for a serverinstance, followed by discovery and dynamic loading of the set ofservices to be hosted within that server instance (duringinitialization, each service creates and registers a single instance ofeach operation class). The call manager, oipsCallMgr, is theninitialized and created.

[0376] B. Document Exchange

[0377] An example of a document exchange between client and server usingthe WSDK APIs is as follows, as illustrated in FIG. 7:

[0378] 1. Client initializes an output document (block 701) by callingoipmInitOutputDoc, selecting the markup as appropriate for itsperformance and compatibility needs. For example, if a large volume ofnon-text data (e.g., .WAV or MP3 files) is to be sent, then the clientmight op to use a markup other than SOAP, which is not well-suited forsuch uses.

[0379] 2. (Assuming use of the above APIs) Client uses the WSDK markuplibrary 4 to add groups and items to the document as appropriate for theservices being requested and then asks for the “serialized”representation of the output document (a data buffer containing the “onthe wire” representation of the document) (block 702). This is done bymaking a number of calls to oipmPut*( ), oipmBeginGroup( ) andoipmEndGroup( ), as appropriate, followed by a call tooipmFinalizeOutput( ) (which allows the implementation to append anymarkup-specific trailer onto the buffer and returns the buffer).

[0380] 3. Client transmits the document to the server (block 703),identifying the markup style in a transport-specific manner. For atypical case where the transport is via an HTTP POST, a URI is used toidentify the markup style (e.g., URL is “http://host:port/oip/soap” or“http://host:port/oip/light”).

[0381] 4. Server reads the request message from client into a databuffer (from socket, file, Apache module API, etc.) (block 704).

[0382] 5. Server invokes the markup library 4 to “parse” the documentinto the input structure (passing the appropriate markup style to themarkup library 4) and initializes an empty output document in the samemarkup style in a data buffer (block 705). In this context, “parsing”includes: 1) parsing from text form into “input document” form, and 2)extracting data from the input document to build a native languagestructure.

[0383] 6. Server invokes the handleCall method of oipsCallMgr to executethe instructions contained in the input document, to populate the outputdocument (block 706).

[0384] 7. Server transmits the output document back to the client, forexample as the reply to the HTTP POST (block 707).

[0385] 8. Client receives and parses the document into an inputstructure (using the markup library 4), passing in the originalrequested markup style (block 708).

[0386] 9. Client traverses the document to determine the results of itsrequest (block 709).

[0387] B. Client Operation

[0388] The actions performed by the client during a document exchangewill now be described in greater detail, with reference to FIG. 8. Theactions performed by the client are as follows:

[0389] 1. Create and initialize a “call” object, specifying the markupstyle and error handling mode desired (block 801).

[0390] 2. For each operation to bundle into the call (blocks 802, 806,812):

[0391] a. Create and initialize an appropriately typed Operationstructure (block 803).

[0392] b. Populate the “request” sub-structure (block 804).

[0393] c. Add the operation to the call (block 805).

[0394] 3. Invoke the “Generate Request” method of the call object (calloipcGenerateRequest) to obtain the markup-specific serializedrepresentation of the request (block 807).

[0395] 4. Send the request message to the server using an appropriatetransport engine and obtain the reply message (block 808).

[0396] 5. Invoke the “Set Reply” method of the call object (calloipcSetReply) to parse the reply message (block 809).

[0397] 6. Examine the “reply” sub-structures as appropriate for each ofthe operations in the call (block 810).

[0398] 7. Clean-up the call object (block 811).

[0399] C. Server Operation

[0400] As discussed above, OipsCallMgr is the top-level manager of thecall dispatch process on the server side. OipsCallMgr has a “handleCall”method, which is invoked by an underlying server framework. ThehandleCall method performs the following process, illustrated in FIG. 9,when a new request message is received:

[0401] 1. Construct a call context, OipsCallCtxt, passing in the requestmessage and the markup style (block 901).

[0402] 2. If the error mode is “rollback” (block 902), initialize thetransaction context (block 903).

[0403] 3. Call oipmNumEntries( ) on the OipsCallCtxt's request documentto find out how many operations exist in the document (block 904).

[0404] 4. For each operation in the document (blocks 905-916):

[0405] a. If the error mode is not “rollback” (block 906), initializethe transaction context (block 907).

[0406] b. Request construction of the appropriate operation contextobject, OpCtxt, from the service manager and add it to the transactionmanager (block 908).

[0407] Service manager reads the service name from the request and asksthe corresponding service for the context.

[0408] The service reads the operation name from the request and asksthe corresponding operation object for the context.

[0409] The operation object constructs and returns an appropriatelytyped operation context object.

[0410] c. Call the operation context's parseRequest( ) method (block909).

[0411] The operation context object uses OipsCallCtxt to find andvalidate the appropriate groups and items and populates “request”structure (data is not copied into request structure—only pointers).

[0412] d. Find the appropriate Operation object and call its “execute()” method, passing the OpCtxt and transaction manager objects to it(block 910).

[0413] e. If the operation execute( ) succeeds (block 911), and if theerror mode is not “rollback” (block 912), invoke “commito” on thetransaction manager (which will write the reply and invoke commit onanything the operation may have added to the transaction manager) anddestroy the transaction manager (block 913).

[0414] f. If the operation execute( ) fails (block 911), then:

[0415] Call “rollback( )” on the transaction manager (block 914). Thiswill call “rollback( )” on anything contained within the transactionmanager (and will write error messages as the replies for any OpCtxtobjects).

[0416] If the error mode is not “continue” (block 915), stop execution(block 916) and return (block 919).

[0417] 5. If the error mode is “rollback” (block 917), call “commit( )”on the transaction manager (see 4e) (block 918).

VIII. Processing System Implementation

[0418] The techniques described above may be implemented in one or moreprocessing systems using software executed by one or more conventionalprocessors, or using special-purpose hardwired circuitry, or acombination thereof. FIG. 10 is a high-level block diagram showing anexample of a processing system that can be used to implement thedescribed techniques. Note that a variety of specific architectures canbe represented by FIG. 10.

[0419] The illustrated system includes one or more processors 101, i.e.a central processing unit (CPU), random access memory (RAM) 102,read-only memory (ROM) 103, and, which may be coupled to each other by abus system 109. The processor(s) 101 may be, or may include, one or moreprogrammable general-purpose or special-purpose microprocessors, digitalsignal processors (DSPs), programmable controllers, application specificintegrated circuits (ASICs), programmable logic devices (PLDs), or acombination of such devices.

[0420] The bus system 109 includes one or more buses or otherconnections, which may be connected to each other through variousbridges, controllers and/or adapters, such as are well-known in the art.For example, the bus system 109 may include a “system bus”, which may beconnected through one or more adapters to one or more expansion buses,such as a Peripheral Component Interconnect (PCI) bus, HyperTransport orindustry standard architecture (ISA) bus, small computer systeminterface (SCSI) bus, universal serial bus (USB), or Institute ofElectrical and Electronics Engineers (IEEE) standard 1394 bus (sometimesreferred to as “Firewire”).

[0421] Also coupled to the bus system 109 are one or more datacommunication devices 104, one or more mass storage devices 105, one ormore input devices 106 and one or more output devices 1010. The inputdevices 106 may include, for example, a keyboard and a pointing device.The output devices 1010 may include, for example, a display device andan audio speaker. Of course, such devices are unnecessary on a server ifthe server is not intended to directly interface with a user oroperator. It will be understood that the processing system may alsoinclude other conventional components that are not shown.

[0422] Each data communication device 44 is a device suitable forenabling the processing system to communicate with remote devices andmay be, for example, a conventional modem, a Digital Subscriber Line(DSL) modem, a cable modem, an Ethernet adapter, an Integrated ServicesDigital Network (ISDN) adapter, a satellite transceiver, a wirelesstransceiver (e.g., in the case of a mobile device), or the like. Eachmass storage device 105 may include any one or more storage mediasuitable for storing large volumes of data in a non-volatile manner,such as a magnetic disk or tape, magneto-optical (MO) storage device, orany of various forms of Digital Versatile Disk (DVD) or Compact Disk(CD) based storage, or a combination thereof.

[0423] The processes described above may be implemented using acombination of instructions and data 108 stored in a storage medium,which may be, for example, any of RAM 102, mass storage device 105and/or ROM 103, as shown, or on a remote processing system.

[0424] Thus, a method and apparatus for requesting and performingbatched operations for Web Services have been described. Although thepresent invention has been described with reference to specificexemplary embodiments, it will be recognized that the invention is notlimited to the embodiments described, but can be practiced withmodification and alteration within the spirit and scope of the appendedclaims. Accordingly, the specification and drawings are to be regardedin an illustrative sense rather than a restrictive sense.

What is claimed is:
 1. A method comprising: dynamically determining in aclient a plurality of batched operations to be performed by a server forthe client during execution of a web based network application, byselecting a portion of an operation structure previously defined using astructured language; operating the client to specify the plurality ofbatched operations in a request; and sending the request from the clientto the server to request the server to perform the plurality ofoperations in a batched mode.
 2. A method as recited in claim 1, whereinthe plurality of batched operations are determined by the clientdynamically based on a current state of execution of the application. 3.A method as recited in claim 1, wherein one of the plurality of batchedoperations uses output of another one of the plurality of batchedoperations as input, when the plurality of batched operations areexecuted.
 4. A method as recited in claim 1, wherein the request furtherspecifies an error handling mode of a plurality of selectable errorhandling modes to determine how an error that occurs during execution ofthe plurality of operations is to be handled, the error-handling modehaving been specified by the client.
 5. A method as recited in claim 4,wherein the plurality of selectable error handling modes include: a stopmode in which execution of the operations is stopped in response to anerror occurring during execution of the operations; a continue mode inwhich execution of the operations continues in response to an erroroccurring during execution of the operations; and a rollback mode inwhich execution of the operations is stopped and a state that existedprior to execution of the operations is resumed, in response to an erroroccurring during execution of the operations.
 6. A method as recited inclaim 1, wherein the client is a mobile client operating on a wirelessnetwork and the server operates on a wireline network.
 7. A method asrecited in claim 1, wherein the request is embodied in a markup languagedocument.
 8. A method for a server to provide a service to a clientduring execution of a web based application in a network environment,the method comprising: generating a request by the client for the serverto perform the service, including creating a call structure including anarray specifying a plurality of batched operations to be performed bythe server, by selecting a portion of an operation structure previouslydefined using a structured language, wherein the plurality of batchedoperations are determined by the client dynamically based on a currentstate of execution of the application, and wherein the call structurefurther includes an indication of a markup language used by the clientand an error handling mode of a plurality of selectable error handlingmodes to determine how an error that occurs during execution of theplurality of operations is to be handled, and including the callstructure in a markup language document; and sending the call structurein a markup language document from the client to the server to requestthe service, such that the server performs the plurality of operationsin the batched mode.
 9. A method as recited in claim 8, wherein theplurality of selectable error handling modes include: a stop mode inwhich execution of the operations is stopped in response to an erroroccurring during execution of the operations; a continue mode in whichexecution of the operations continues in response to an error occurringduring execution of the operations; and a rollback mode in whichexecution of the operations is stopped and a state that existed prior toexecution of the operations is resumed, in response to an erroroccurring during execution of the operations.
 10. A method as recited inclaim 8, wherein the client is a mobile client operating on a wirelessnetwork and the server operates on a wireline network.
 11. A method asrecited in claim 8, wherein one of the plurality of batched operationsuses output of another one of the plurality of batched operations asinput, when the plurality of batched operations are executed.
 12. Amethod comprising: receiving a request at a server from a client duringexecution of a web based network application, the request specifying aplurality of batched operations associated with a service to be providedby the server to the client, the plurality of batched operations havingbeen determined by the client dynamically by the client selecting aportion of an operation structure previously defined using a structuredlanguage; and operating the server to perform the plurality ofoperations in a batched mode.
 13. A method as recited in claim 12,wherein the plurality of batched operations have been determined by theclient based on a current state of execution of the application.
 14. Amethod as recited in claim 12, wherein one of the plurality of batchedoperations uses output of another one of the plurality of batchedoperations as input, when the plurality of batched operations areexecuted.
 15. A method as recited in claim 12, wherein the requestfurther specifies an error handling mode of a plurality of selectableerror handling modes to determine how an error that occurs duringexecution of the plurality of operations is to be handled, theerror-handling mode having been specified by the client.
 16. A method asrecited in claim 15, wherein the plurality of selectable error handlingmodes include: a stop mode in which execution of the operations isstopped in response to an error occurring during execution of theoperations; a continue mode in which execution of the operationscontinues in response to an error occurring during execution of theoperations; and a rollback mode in which execution of the operations isstopped and a state that existed prior to execution of the operations isresumed, in response to an error occurring during execution of theoperations.
 17. A method as recited in claim 12, wherein the client is amobile client operating on a wireless network and the server operates ona wireline network.
 18. A method as recited in claim 12, wherein therequest is embodied in a markup language document.